package com.itheima.book.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.book.mapper.CategoryMapper;
import com.itheima.book.service.CategoryAdminService;
import com.itheima.model.book.dtos.CategoryAdminDto;
import com.itheima.model.book.dtos.CategorySaveDto;
import com.itheima.model.book.pojos.Category;
import com.itheima.model.common.dtos.PageResponseResult;
import com.itheima.model.common.dtos.ResponseResult;
import com.itheima.model.common.enums.AppHttpCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 分类管理后台服务实现
 * 
 * @author itheima
 */
@Slf4j
@Service
public class CategoryAdminServiceImpl implements CategoryAdminService {

    @Autowired
    private CategoryMapper categoryMapper;

    @Override
    public ResponseResult listCategories(CategoryAdminDto dto) {
        try {
            // 校验参数
            dto.checkParam();

            // 构建查询条件
            LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();

            // 分类名称模糊查询
            if (StringUtils.hasText(dto.getName())) {
                queryWrapper.like(Category::getName, dto.getName());
            }

            // 父级分类精确查询
            if (dto.getParentId() != null) {
                queryWrapper.eq(Category::getParentId, dto.getParentId());
            }

            // 状态查询
            if (dto.getIsEnabled() != null) {
                queryWrapper.eq(Category::getIsEnabled, dto.getIsEnabled());
            }

            // 按排序字段升序，创建时间倒序
            queryWrapper.orderByAsc(Category::getSort)
                       .orderByDesc(Category::getCreateTime);

            // 分页查询
            IPage<Category> pageObj = new Page<>(dto.getPage(), dto.getSize());
            IPage<Category> result = categoryMapper.selectPage(pageObj, queryWrapper);

            // 构建响应结果
            PageResponseResult pageResponse = new PageResponseResult(
                dto.getPage(), 
                dto.getSize(), 
                (int) result.getTotal()
            );
            pageResponse.setData(result.getRecords());

            return pageResponse;
        } catch (Exception e) {
            log.error("查询分类列表失败", e);
            return ResponseResult.errorResult(500, "查询分类列表失败：" + e.getMessage());
        }
    }

    @Override
    public ResponseResult getCategoryById(Integer id) {
        try {
            if (id == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "分类ID不能为空");
            }

            Category category = categoryMapper.selectById(id);
            if (category == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "分类不存在");
            }

            return ResponseResult.okResult(category);
        } catch (Exception e) {
            log.error("获取分类详情失败, id={}", id, e);
            return ResponseResult.errorResult(500, "获取分类详情失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public ResponseResult addCategory(CategorySaveDto dto) {
        try {
            // 检查分类名称是否已存在
            LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Category::getName, dto.getName());
            if (dto.getParentId() != null) {
                queryWrapper.eq(Category::getParentId, dto.getParentId());
            }
            int count = categoryMapper.selectCount(queryWrapper).intValue();
            if (count > 0) {
                return ResponseResult.errorResult(500, "该层级下已存在同名分类");
            }

            // 如果有父级分类，检查父级是否存在
            if (dto.getParentId() != null && dto.getParentId() > 0) {
                Category parent = categoryMapper.selectById(dto.getParentId());
                if (parent == null) {
                    return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "父级分类不存在");
                }
            }

            Category category = new Category();
            BeanUtils.copyProperties(dto, category);
            
            // 设置默认值
            if (category.getSort() == null) {
                category.setSort(0);
            }
            if (category.getIsEnabled() == null) {
                category.setIsEnabled(Category.ENABLE);
            }
            
            category.setCreateTime(new Date());
            category.setUpdateTime(new Date());

            int result = categoryMapper.insert(category);
            if (result > 0) {
                return ResponseResult.okResult(category);
            } else {
                return ResponseResult.errorResult(500, "新增分类失败");
            }
        } catch (Exception e) {
            log.error("新增分类失败", e);
            return ResponseResult.errorResult(500, "新增分类失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public ResponseResult updateCategory(CategorySaveDto dto) {
        try {
            if (dto.getId() == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "分类ID不能为空");
            }

            // 检查分类是否存在
            Category existCategory = categoryMapper.selectById(dto.getId());
            if (existCategory == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "分类不存在");
            }

            // 检查分类名称是否与其他分类重复
            LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Category::getName, dto.getName())
                       .eq(Category::getParentId, dto.getParentId())
                       .ne(Category::getId, dto.getId());
            int count = categoryMapper.selectCount(queryWrapper).intValue();
            if (count > 0) {
                return ResponseResult.errorResult(500, "该层级下已存在同名分类");
            }

            // 如果修改了父级分类，检查是否会形成循环引用
            if (dto.getParentId() != null && !dto.getParentId().equals(existCategory.getParentId())) {
                if (isCircularReference(dto.getId(), dto.getParentId())) {
                    return ResponseResult.errorResult(500, "不能将分类设置为自己或其子分类的下级");
                }
            }

            Category category = new Category();
            BeanUtils.copyProperties(dto, category);
            category.setUpdateTime(new Date());

            int result = categoryMapper.updateById(category);
            if (result > 0) {
                return ResponseResult.okResult(category);
            } else {
                return ResponseResult.errorResult(500, "更新分类失败");
            }
        } catch (Exception e) {
            log.error("更新分类失败, id={}", dto.getId(), e);
            return ResponseResult.errorResult(500, "更新分类失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public ResponseResult deleteCategory(Integer id) {
        try {
            if (id == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "分类ID不能为空");
            }

            // 检查分类是否存在
            Category category = categoryMapper.selectById(id);
            if (category == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "分类不存在");
            }

            // 检查是否有子分类
            LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Category::getParentId, id);
            int childCount = categoryMapper.selectCount(queryWrapper).intValue();
            if (childCount > 0) {
                return ResponseResult.errorResult(500, "该分类下存在子分类，无法删除");
            }

            // 检查该分类下是否有图书（需要调用book表查询，这里暂时省略）
            // TODO: 检查分类下是否有图书

            int result = categoryMapper.deleteById(id);
            if (result > 0) {
                return ResponseResult.okResult("删除成功");
            } else {
                return ResponseResult.errorResult(500, "删除分类失败");
            }
        } catch (Exception e) {
            log.error("删除分类失败, id={}", id, e);
            return ResponseResult.errorResult(500, "删除分类失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public ResponseResult updateCategoryStatus(Integer id, Integer isEnabled) {
        try {
            if (id == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "分类ID不能为空");
            }

            if (isEnabled == null || (isEnabled != 0 && isEnabled != 1)) {
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "状态参数无效");
            }

            // 检查分类是否存在
            Category category = categoryMapper.selectById(id);
            if (category == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "分类不存在");
            }

            category.setIsEnabled(isEnabled);
            category.setUpdateTime(new Date());

            int result = categoryMapper.updateById(category);
            if (result > 0) {
                return ResponseResult.okResult("状态更新成功");
            } else {
                return ResponseResult.errorResult(500, "状态更新失败");
            }
        } catch (Exception e) {
            log.error("更新分类状态失败, id={}", id, e);
            return ResponseResult.errorResult(500, "更新分类状态失败：" + e.getMessage());
        }
    }

    @Override
    public ResponseResult getParentCategories() {
        try {
            // 查询所有一级分类（parentId为0）和启用的二级分类
            LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Category::getIsEnabled, Category.ENABLE)
                       .orderByAsc(Category::getLevel)
                       .orderByAsc(Category::getSort);
            
            List<Category> categories = categoryMapper.selectList(queryWrapper);
            
            // 过滤出可作为父级的分类（一般是一级和二级分类）
            List<Category> parentCategories = categories.stream()
                .filter(c -> c.getLevel() <= 2)
                .collect(Collectors.toList());

            return ResponseResult.okResult(parentCategories);
        } catch (Exception e) {
            log.error("获取父级分类列表失败", e);
            return ResponseResult.errorResult(500, "获取父级分类列表失败：" + e.getMessage());
        }
    }

    /**
     * 检查是否会形成循环引用
     * @param categoryId 当前分类ID
     * @param newParentId 新的父级ID
     * @return true-会形成循环引用，false-不会
     */
    private boolean isCircularReference(Integer categoryId, Integer newParentId) {
        if (newParentId == null || newParentId == 0) {
            return false;
        }
        
        if (categoryId.equals(newParentId)) {
            return true;
        }

        Category parent = categoryMapper.selectById(newParentId);
        if (parent == null) {
            return false;
        }

        return isCircularReference(categoryId, parent.getParentId());
    }
}

